package com.xhwl.data.controller;


import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.xhwl.common.enums.LogOperationTypeEnum;
import com.xhwl.common.dto.cent.sdata.*;
import com.xhwl.common.enums.*;
import com.xhwl.common.enums.config.BusinessType;
import com.xhwl.common.enums.config.PermissionTypeEnum;
import com.xhwl.common.enums.config.RoleTypeEnum;
import com.xhwl.common.exception.DataException;
import com.xhwl.common.pojo.ResultJson;
import com.xhwl.common.pojo.cent.sdata.*;
import com.xhwl.common.pojo.cent.sdata.devplatform.Developer;
import com.xhwl.common.query.cent.sdata.AppQuery;
import com.xhwl.common.query.cent.sdata.EnterpriseQuery;
import com.xhwl.common.query.cent.sdata.PermissionQuery;
import com.xhwl.common.query.cent.sdata.ProjectQuery;
import com.xhwl.common.utils.excel.ExcelUtils;
import com.xhwl.common.vo.cent.sdata.PermissionVO;
import com.xhwl.data.dao.ISceneDao;
import com.xhwl.data.pojo.PermissionAuth;
import com.xhwl.data.pojo.PermissionAuthDTO;
import com.xhwl.data.pojo.vo.PermissionExcelVO;
import com.xhwl.data.pojo.vo.PermissionTypeVO;
import com.xhwl.data.service.*;
import com.xhwl.data.util.EnumListUtil;
import com.xhwl.data.util.excel.ExcelExportUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * @Author: luyi
 * @Description:
 * @Date: Create in 3:37 下午 2020/9/28
 */
@RestController
public class PermissionController {

    private static final Logger log = LoggerFactory.getLogger(PermissionController.class);
    @Autowired
    IAccountService accountService;
    @Autowired
    IPermissionService permissionService;
    @Autowired
    ExcelExportUtils excelExportUtils;
    @Autowired
    ISceneDao sceneDao;
    @Autowired
    IAppService appService;
    @Autowired
    IRoleService roleService;
    @Autowired
    IOrganizationService organizationService;
    @Autowired
    IProjectService projectService;
    @Autowired
    IAccountProjectService accountProjectService;
    @Autowired
    IMenuModuleService menuModuleService;
    @Autowired
    IProjectPermissionService projectPermissionService;
    @Autowired
    IAdminAccountRoleService adminAccountRoleService;
    @Autowired
    IPermissionGroupService permissionGroupService;
    @Autowired
    IEnterpriseService enterpriseService;
    @Autowired
    private IEnterpriseAppService enterpriseAppService;
    @Autowired
    private IAccountRoleService accountRoleService;

    @Autowired
    private IPermissionAuthService permissionAuthService;

    //enterpriseAdd 新增企业
    //enterpriseModify 修改企业
    //enterpriseDetail 查看企业
    //projectAdd 新增项目
    //projectModify 修改项目
    private static final List<String> EXCLUDE_PROJECT_PERMISSION = Arrays.asList("enterpriseAdd", "enterpriseModify", "enterpriseDetail", "projectAdd", "projectModify");
    //enterpriseAdd 新增企业
    //enterpriseModify 修改企业
    private static final List<String> EXCLUDE_ENTERPRISE_PERMISSION = Arrays.asList("enterpriseAdd", "enterpriseModify");

    private static final String COMMON_MODULE = "COMMON";
    //注册的游客角色
    private String REGISTER_TOURIST_ROLE_CODE = "TOURIST1";


    /**
     * 功能模块选择器 （日志查询页面）
     *
     * @return
     */
    @GetMapping(value = "/permissions/get-module-list")
    public ResultJson getModuleTypes(@RequestHeader(value = "appId", required = false) String appId,
                                     @RequestHeader(value = "clientType", required = false) Integer clientType,
                                     @RequestHeader(value = "industryId", required = false) Short industryId) {
        List<MenuModule> moduleTypes = menuModuleService.generateTree();
        return ResultJson.success(moduleTypes);
    }

    /**
     * 操作类型选择器 （日志查询页面）
     *
     * @return
     */
    @GetMapping(value = "/permissions/get-operate-list")
    public ResultJson getOperateTypes(@RequestHeader(value = "appId", required = true) String appId,
                                      @RequestHeader(value = "clientType", required = false) Integer clientType,
                                      @RequestHeader(value = "industryId", required = true) Short industryId,
                                      @RequestParam(value = "moduleNames", required = false) List<String> moduleNames,
                                      @RequestParam(value = "needAll", required = false) Boolean needAll) {
        List<Map<String, Object>> operationTypes = EnumListUtil.enumToListMap(LogOperationTypeEnum.class);
        if (null != needAll) {
            if (needAll) {
                return ResultJson.success(operationTypes);
            }
        }
        List<Map<String, Object>> operationTypesResult = new ArrayList<>(operationTypes.size());
        for (Map<String, Object> map : operationTypes) {
            String moduleName = (String) map.get("module");
            if (COMMON_MODULE.equals(moduleName)) {
                operationTypesResult.add(map);
            } else {
                if (!CollectionUtils.isEmpty(moduleNames)) {
                    if (moduleNames.contains(moduleName)) {
                        operationTypesResult.add(map);
                    }
                }
            }
        }
        return ResultJson.success(operationTypesResult);
    }

    /**
     * 修改/新增角色 时的权限树 获取
     *
     * @param id 角色id
     * @param organizationId
     * @param type
     * @param operateAccount
     * @return
     */
    @RequestMapping(value = "/permissions/role-permissions-tree", method = RequestMethod.GET)
    public ResultJson rolePermissionsTree(
            @RequestHeader(value = "industryId") Integer industryId,
            @RequestParam(value = "id", required = false) Integer id,
            @RequestParam(value = "organizationId", required = false) Integer organizationId,
            @RequestParam(value = "type", required = false) Integer type,
            @RequestParam(value = "enterpriseId", required = false) Integer enterpriseId,
            Account operateAccount) {
        List<Enterprise> enterprises = enterpriseService.findByAccount(operateAccount);
        if(enterprises.isEmpty()){
            return ResultJson.fail("帐号暂未关联企业");
        }
        if(null == enterpriseId){
            enterpriseId = enterprises.get(0).getId();
        }
        // 获取当前企业的企业权限
        List<Permission> listByEnterpriseId = permissionService.getListByEnterpriseId(null, enterpriseId);
        if(CollectionUtils.isEmpty(listByEnterpriseId)){
            return ResultJson.fail("企业暂无权限");
        }
        List<Integer> enterprisePermissionIds = listByEnterpriseId.stream().map(j -> j.getId()).collect(Collectors.toList());
        PermissionTreeDTO permissionTreeDTO = new PermissionTreeDTO();
        permissionTreeDTO.setIds(enterprisePermissionIds);
        permissionTreeDTO.setIndustryId(industryId);
        List<AppPermissionMenuDTO> permissionTree1 = permissionService.getPermissionTree(permissionTreeDTO);
        return ResultJson.success(permissionTree1);
    }


    /**
     * 修改/新增项目时的权限树获取
     * @deprecated 前台没有修改项目的地方了
     * @param enterpriseId
     * @param operateAccount
     * @return
     */
    @Deprecated
    @RequestMapping(value = "/permissions/project-permissions-tree", method = RequestMethod.GET)
    public ResultJson projectPermissionsTree(Account operateAccount, @RequestParam(value = "enterpriseId", required = false) Integer enterpriseId) {
        PermissionTreeDTO permissionTreeDTO = new PermissionTreeDTO();
        // 查询企业下的app
        QueryWrapper<EnterpriseApp> enterpriseAppQueryWrapper = new QueryWrapper<>();
        enterpriseAppQueryWrapper.select("app_id");
        enterpriseAppQueryWrapper.eq("enterprise_id", enterpriseId);
        List<EnterpriseApp> enterpriseApps = enterpriseAppService.list(enterpriseAppQueryWrapper);
        if(CollectionUtils.isEmpty(enterpriseApps)){
            log.warn("企业 {} 没有关联app", enterpriseId);
            return ResultJson.success(Collections.emptyList());
        }
        permissionTreeDTO.setAppIds(enterpriseApps.stream().map(i -> i.getAppId()).distinct().collect(Collectors.toList()));
        permissionTreeDTO.setNeedButton(false);
        permissionTreeDTO.setNeedAdmin(true);
        List<AppPermissionMenuDTO> permissionTree = permissionService.getPermissionTreeAdmin(permissionTreeDTO);
        return ResultJson.success(permissionTree);
    }

    /**
     * 后台获取 修改/新增项目时的权限树
     * @param enterpriseId
     * @return
     */
    @GetMapping(value = "/permissions/admin/project-permissions-tree")
    public ResultJson adminProjectPermissionsTree(@RequestParam(value = "enterpriseId", required = false) Integer enterpriseId){
        PermissionTreeDTO permissionTreeDTO = new PermissionTreeDTO();

        // 查询企业下的app
        QueryWrapper<EnterpriseApp> enterpriseAppQueryWrapper = new QueryWrapper<>();
        enterpriseAppQueryWrapper.select("app_id");
        if(null != enterpriseId){
            enterpriseAppQueryWrapper.eq("enterprise_id", enterpriseId);
        }
        List<EnterpriseApp> enterpriseApps = enterpriseAppService.list(enterpriseAppQueryWrapper);
        if(CollectionUtils.isEmpty(enterpriseApps)){
            log.warn("企业 {} 没有关联app", enterpriseId);
            return ResultJson.success(Collections.emptyList());
        }
        permissionTreeDTO.setAppIds(enterpriseApps.stream().map(i -> i.getAppId()).distinct().collect(Collectors.toList()));
        permissionTreeDTO.setMenuTypes(Arrays.asList(1, 2));
        permissionTreeDTO.setNeedAdmin(true);
        permissionTreeDTO.setPermissionType(PermissionTypeEnum.PROJECT);
        if(null != enterpriseId){
            permissionTreeDTO.setEnterpriseId(enterpriseId);
        }
        return ResultJson.success(permissionService.getPermissionTreeAdmin(permissionTreeDTO));
    }

    /**
     * 前台 修改/新增 企业时的权限树获取 过滤掉项目范围的权限
     *
     * @param enterpriseId
     * @param operateAccount
     * @return
     */
    @RequestMapping(value = "/permissions/enterprise-permissions-tree", method = RequestMethod.GET)
    public ResultJson enterprisePermissionsTree(@RequestHeader(value = "appId", required = true) String appId,
                                                @RequestHeader(value = "industryId", required = true) Short industryId,
                                                @RequestParam(value = "enterpriseId", required = false) Integer enterpriseId,
                                                Account operateAccount) {
        Enterprise enterprise = enterpriseService.findById(enterpriseId);
        if(null == enterprise){
            return ResultJson.fail("企业不存在");
        }
        PermissionTreeDTO permissionTreeDTO = new PermissionTreeDTO();
        permissionTreeDTO.setEnterpriseId(enterprise.getId());
        permissionTreeDTO.setMenuTypes(Arrays.asList(1, 2));
        permissionTreeDTO.setNeedAdmin(true);
        permissionTreeDTO.setPermissionType(PermissionTypeEnum.ENTERPRISE);
        List<AppPermissionMenuDTO> permissionTree = permissionService.getPermissionTree(permissionTreeDTO, operateAccount);
        List<AppPermissionMenuDTO> permissionTreeResult = new ArrayList<>();
        if (!CollectionUtils.isEmpty(permissionTree)) {
            for (AppPermissionMenuDTO appPermissionMenuDTO : permissionTree) {
                Short industryIdForPermission = appPermissionMenuDTO.getApp().getIndustryId();
                if (industryId.equals(industryIdForPermission)) {
                    permissionTreeResult.add(appPermissionMenuDTO);
                }
            }
            return ResultJson.success(permissionTreeResult);
        }
        return ResultJson.success(permissionTree);
    }

    /**
     * 门户 企业查菜单权限
     */
    @RequestMapping(value = "/permissions/permissionsTreeProject")
    public ResultJson permissionsTreeProject(@RequestHeader(value = "appId", required = true) String appId,
                                             @RequestBody PermissionTreeDTO permissionTreeDTO,
                                             Account operateAccount) {
        if(permissionTreeDTO.getEnterpriseId() == null && CollectionUtils.isEmpty(permissionTreeDTO.getProjectIds())){
            return ResultJson.fail("参数为空");
        }
        QueryWrapper<Project> queryWrapper =new QueryWrapper<>();
        if(CollectionUtils.isEmpty(permissionTreeDTO.getProjectIds()) && permissionTreeDTO.getEnterpriseId() != null){
            queryWrapper.eq("enterprise_id",permissionTreeDTO.getEnterpriseId());
        }
        if(!CollectionUtils.isEmpty(permissionTreeDTO.getProjectIds())) {
            queryWrapper.in("id", permissionTreeDTO.getProjectIds());
        }
        List<Project> projectList = projectService.list(queryWrapper);
        if(null == projectList){
            return ResultJson.fail("项目不存在");
        }
        List<ProjectPermissionMenuDTO> result = new ArrayList<>();
        ProjectPermissionMenuDTO projectPermissionMenuDTO = null;
        for(Project vo :projectList){
            projectPermissionMenuDTO = new ProjectPermissionMenuDTO();
            projectPermissionMenuDTO.setProject(vo);
            PermissionTreeDTO param = new PermissionTreeDTO();
            param.setProjectId(vo.getId());
            //permissionTreeDTO.setEnterpriseId(enterprise.getId());
            //permissionTreeDTO.setMenuTypes(Arrays.asList(1, 2));
            param.setNeedAdmin(true);
           // permissionTreeDTO.setPermissionType(PermissionTypeEnum.ENTERPRISE);
            List<AppPermissionMenuDTO> permissionTree = permissionService.getPermissionTree(param, operateAccount);
            projectPermissionMenuDTO.setAppPermissionMenuDTOS(permissionTree);
            result.add(projectPermissionMenuDTO);
        }
        return ResultJson.success(result);
    }

    /**
     * 后台修改/新增企业时的权限树获取
     * @return
     */
    @GetMapping(value = "/permissions/admin/enterprise-permissions-tree")
    public ResultJson adminEnterprisePermissionsTree(@RequestHeader(value = "appId", required = true) String appId,
                                                     @RequestHeader(value = "industryId", required = true) Short industryId,
                                                     @RequestParam(value = "enterpriseId", required = false) Integer enterpriseId, Developer developer){
        PermissionTreeDTO permissionTreeDTO = new PermissionTreeDTO();
        permissionTreeDTO.setDevelopId(developer.getId());
//        permissionTreeDTO.setNeedButton(false);
        permissionTreeDTO.setNeedAdmin(true);
//        permissionTreeDTO.setPermissionType(PermissionTypeEnum.ENTERPRISE);
        return ResultJson.success(permissionService.getPermissionTreeAdmin(permissionTreeDTO));
    }

    /**
     * 后台（运管平台）获取企业项目角色的权限
     * @param permissionTreeDTO
     * @return
     */
    @RequestMapping(value = "/permissions/admin-permissions-tree")
    public ResultJson getPermissionTreeAdmin(@RequestBody PermissionTreeDTO permissionTreeDTO, Developer developer){
        // 查询开发者下的权限
        permissionTreeDTO.setDevelopId(developer.getId());
        if(null != permissionTreeDTO.getProjectId()){
            permissionTreeDTO.setPermissionType(PermissionTypeEnum.PROJECT);
        }
        List<AppPermissionMenuDTO> permissionTree = permissionService.getPermissionTreeAdmin(permissionTreeDTO);
        return ResultJson.success(permissionTree);
    }

    /**
     * 后台（运管平台）获取企业项目角色的权限
     */
    @RequestMapping(value = "/permissions/admin/permissions-tree")
    public ResultJson permissionTreeAdmin(@RequestBody PermissionTreeDTO permissionTreeDTO, Developer developer){
        // 查询开发者下的权限
        permissionTreeDTO.setDevelopId(developer.getId());
        List<ScenePermissionMenuDTO> permissionTree = permissionService.permissionTreeAdmin(permissionTreeDTO);
        return ResultJson.success(permissionTree);
    }


    /**
     * 根据角色/项目/企业获取权限list 用于勾选的角色信息
     *
     * @param enterpriseId
     * @param projectId
     * @param roleId
     * @return
     */
    @RequestMapping(value = "/permissions/get-code-list", method = RequestMethod.GET)
    public ResultJson getCodeList(@RequestParam(value = "enterpriseId", required = false) Integer enterpriseId,
                                  @RequestParam(value = "projectId", required = false) Integer projectId,
                                  @RequestParam(value = "roleId", required = false) Integer roleId,
                                  @RequestParam(value = "appId", required = false) String appId) {
        List<Permission> permissionList = null;
        if (null != enterpriseId) {
            permissionList = permissionService.getListByEnterpriseId(null, enterpriseId);
            return ResultJson.success(permissionList);
        }
        if (null != projectId) {
            permissionList = permissionService.getListByProjectId(null, projectId);
            return ResultJson.success(permissionList);
        }
        if (null != roleId) {
            permissionList = permissionService.getListByRoleId(appId, roleId);
            return ResultJson.success(permissionList);
        }
        return ResultJson.fail("查询失败");
    }

    /**
     * 根据账号获取权限菜单树 (业务平台，住宅商写 使用)
     * 根据帐号角色获取的权限再与企业项目取交集
     *
     * @param operateAccount
     * @return
     */
    @RequestMapping(value = "/permissions/menu", method = RequestMethod.GET)
    public ResultJson menuList(Account operateAccount,
                               @RequestHeader(value = "industryId", required = true) Short industryId,
                               @RequestHeader(value = "appId", required = true) String appId,
                               @RequestParam(value = "projectId", required = false) Integer projectId) {
        //如果operateAccount为空，则返回游客默认查看的菜单
        if (null == operateAccount) {
            log.info("操作账号信息为空，返回默认菜单");
            List<PermissionDTO> defaultPermissionTree = permissionService.getDefaultPermissionTree(appId, false);
            return ResultJson.success(defaultPermissionTree);
        }
        List<PermissionDTO> covertResultList = new ArrayList<>();
        //获取当前登录操作账号的角色身份
        RoleTypeDTO roleTypeDTO = roleService.getAccountRoleType(operateAccount.getId());
        RoleTypeEnum operateRoleType = roleTypeDTO.getRoleTypeEnum();
        //拦截传入无效的项目id
        if (Objects.nonNull(projectId)) {
            Project projectDb = projectService.findById(projectId);
            if (Objects.isNull(projectDb)) {
                log.warn("当前传入的项目id在数据库内不存在,projectId={}", projectId);
                return ResultJson.success(covertResultList);
            }
        }
        //企管、项管需要做权限处理
        if (RoleTypeEnum.ENT_MANAGER.equals(operateRoleType)) {
            List<Integer> enterpriseIdList = roleTypeDTO.getEnterpriseIdList();
            ProjectQuery projectQuery = new ProjectQuery();
            projectQuery.withEnterpriseIds(enterpriseIdList);
            List<Project> projectList = projectService.list(projectQuery, null);
            List<Integer> proIds = projectList.stream().map(Project::getId).collect(Collectors.toList());
            if (Objects.nonNull(projectId)) {
                if (!proIds.contains(projectId)) {
                    log.warn("当前传入的项目id={}与当前账号拥有的项目权限 无交集={}", projectId, proIds.toString());
                    return ResultJson.success(covertResultList);
                }
            }
        } else {
            Integer operateAccountId = operateAccount.getId();
            List<Integer> projectIdList = accountProjectService.list(operateAccountId, null);
            ProjectQuery projectQuery = new ProjectQuery();
            projectQuery.withIdList(projectIdList);
            List<Project> projectList = projectService.list(projectQuery, null);
            List<Integer> proIds = projectList.stream().map(Project::getId).collect(Collectors.toList());
            if (Objects.nonNull(projectId)) {
                if (!proIds.contains(projectId)) {
                    log.warn("当前传入的项目id={}与当前账号拥有的项目权限 无交集={}", projectId, proIds.toString());
                    return ResultJson.success(covertResultList);
                }
            }
        }
        covertResultList = permissionService.getPermissionTreeByAccount(operateAccount, projectId, appId);
        return ResultJson.success(covertResultList);
    }

    /**
     * 获取帐号的权限（菜单）通过权限组获取
     * @return
     */
    @PostMapping(value = "/permissions/menu/v2")
    public ResultJson menuV2(@RequestHeader(value = "appId", required = true) String appId,
                             @RequestHeader(value = "industryId") Short industryId,
                             @RequestBody PermissionQuery permissionQuery, Account account){

        // 开放平台前台和业态平台没法兼容
//        if(null == permissionQuery.getEnterpriseId()){
//            List<Enterprise> list = enterpriseService.list(new EnterpriseQuery(), account);
//            if(CollectionUtils.isEmpty(list)){
//                return ResultJson.fail("该帐号没有关联企业信息");
//            }
//            permissionQuery.setEnterpriseId(list.get(0).getId());
//        }
        if (null == account) {
            log.info("操作账号信息为空，返回默认菜单");
            List<PermissionDTO> defaultPermissionTree = permissionService.getDefaultPermissionTree(appId, false);
            return ResultJson.success(defaultPermissionTree);
        }
        RoleTypeDTO roleTypeDTO = roleService.getAccountRoleType(account.getId());
        // 企业超管获取权限
        if(RoleTypeEnum.ENT_MANAGER == roleTypeDTO.getRoleTypeEnum()){
            log.info("企业超管获取企业的全部权限菜单");
            permissionQuery.setAccountId(account.getId());
            permissionQuery.setIndustryId(industryId);
            List<PermissionDTO> permissionTreeByAccount = permissionService.getPermissionTreeByAccount(account, permissionQuery, appId);
            return ResultJson.success(permissionTreeByAccount);
        }
        permissionQuery.setAccountId(account.getId());
        permissionQuery.setIndustryId(industryId);
        // 只查询当前应用的菜单
        permissionQuery.setAppId(appId);
        List<PermissionDTO> permissionDTOS = permissionService.getPermissionFromGroup(permissionQuery);
        return ResultJson.success(permissionDTOS);
    }

    /**
     * 获取后台的权限
     * @param adminAccount
     * @param appId
     * @return
     */
    @RequestMapping(value = "/permissions/admin/menu")
    public ResultJson adminMenu(AdminAccount adminAccount, App app,
                               @RequestHeader(value = "appId", required = true) String appId) {
        if(null == adminAccount || null == adminAccount.getId()){
            return ResultJson.fail(CodeEnum.TOKEN_ERROR.code, "获取登录信息失败");
        }
        List<PermissionDTO> adminPermissionTree = permissionService.getAdminAccountPermissionTree(adminAccount, app);
        return ResultJson.success(adminPermissionTree);
    }

    /**
     * 根据账号获取权限List
     *
     * @param operateAccount
     * @return
     */
    @RequestMapping(value = "/permissions/all-code", method = RequestMethod.GET)
    public ResultJson allCode(@RequestHeader(value = "industryId", required = true) Short industryId,
                              @RequestHeader(value = "appId", required = true) String appId,
                              @RequestParam(value = "projectId", required = false) Integer projectId,
                              Account operateAccount) {

        //appId 转换,将string类型的appId转化为对应的主键
        App app = appService.getByAppId(appId);
        if (Objects.isNull(app)) {
            log.info("当前数据库无此appId={}相关数据，请核实", appId);
            return ResultJson.fail("app数据异常");
        }
        Integer appKeyId = app.getId();
        PermissionQuery permissionQuery = new PermissionQuery();
        permissionQuery.setAccountId(operateAccount.getId());
        permissionQuery.setAppIdPrimaryKey(appKeyId);
        List<Permission> permissionList = permissionService.getPermissionList(permissionQuery);
        if (CollectionUtils.isEmpty(permissionList)) {
            return ResultJson.success(Collections.emptyList());
        }
        //如果是app类型，需要加入默认的菜单去重
        if (AppTypeEnum.APP.getType() == app.getAppType()) {
            //将属于这个app的所有菜单获取出来
            List<Permission> defaultPermissions = permissionService.getDefaultPermissions(appId, true);
            permissionList.addAll(defaultPermissions);
            Set<Permission> permissionSet = new HashSet<>(permissionList);
            permissionList = new ArrayList<>(permissionSet);
        }
        List<PermissionVO> resultList = new ArrayList<>();
        //appId过滤
        for (Permission permission : permissionList) {
            Integer appKeyIdDb = permission.getAppId();
            if (appKeyId.equals(appKeyIdDb)) {
                PermissionVO permissionVO = new PermissionVO();
                BeanUtils.copyProperties(permission, permissionVO);
                permissionVO.setAppId(appId);
                resultList.add(permissionVO);
            }
        }
        RoleTypeDTO accountRoleInfos = roleService.getAccountRoleType(operateAccount.getId());
        RoleTypeEnum roleTypeEnum = accountRoleInfos.getRoleTypeEnum();
        //超管特殊处理 -业态下所有的角色权限 permissionCode都能拥有
        if (!roleTypeEnum.equals(RoleTypeEnum.SUPPER_MANAGER)) {
            //项目id过滤
            List<Integer> resultIds = resultList.stream().map(PermissionVO::getId).collect(Collectors.toList());
            List<Integer> filterByProject = new ArrayList<>();
            if (null != projectId) {
                List<ProjectPermission> list = projectPermissionService.getList(Arrays.asList(projectId), resultIds);
                if (!CollectionUtils.isEmpty(list)) {
                    filterByProject = list.stream().map(ProjectPermission::getPermissionId).collect(Collectors.toList());
                }
            }
            List<PermissionVO> returnList = new ArrayList<>();
            if (!CollectionUtils.isEmpty(filterByProject)) {
                for (PermissionVO permissionVO : resultList) {
                    Integer id = permissionVO.getId();
                    if (filterByProject.contains(id)) {
                        returnList.add(permissionVO);
                    }
                }
            } else {
                returnList.addAll(resultList);
            }
            return ResultJson.success(returnList);
        }
        return ResultJson.success(resultList);
    }


    /**
     * 新增
     *
     * @param appPermissionDTO
     * @param appId
     * @param clientType
     * @param industryId
     * @return
     */
    @RequestMapping(value = "/permission/create", method = RequestMethod.POST)
    public ResultJson create(@RequestBody AppPermissionDTO appPermissionDTO,
                             @RequestHeader(value = "appId", required = true) String appId,
                             @RequestHeader(value = "clientType", required = true) Integer clientType,
                             @RequestHeader(value = "industryId", required = true) Short industryId) {
        return permissionService.createPermission(appPermissionDTO);
    }

    /**
     * 修改
     *
     * @param AppPermissionDTO
     * @param appId
     * @param clientType
     * @param industryId
     * @return
     */
    @RequestMapping(value = "/permission/update", method = RequestMethod.POST)
    public ResultJson update(@RequestBody AppPermissionDTO AppPermissionDTO,
                             @RequestHeader(value = "appId", required = true) String appId,
                             @RequestHeader(value = "clientType", required = true) Integer clientType,
                             @RequestHeader(value = "industryId", required = true) Short industryId) {
        return permissionService.updatePermission(AppPermissionDTO);
    }

    /**
     * 删除
     *
     * @param permissionIds
     * @param appId
     * @param clientType
     * @param industryId
     * @return
     */
    @RequestMapping(value = "/permission/delete", method = RequestMethod.GET)
    public ResultJson delete(@RequestParam(value = "permissionIds", required = true) List<Integer> permissionIds,
                             @RequestHeader(value = "appId", required = true) String appId,
                             @RequestHeader(value = "clientType", required = true) Integer clientType,
                             @RequestHeader(value = "industryId", required = true) Short industryId) {
        log.info("正在执行删除权限接口,permissionIds={}", permissionIds);
        return permissionService.deletePermission(permissionIds);
    }

    /**
     * 批量更新权限类型 把权限标记成项目级
     * @param permissionTypeVOs
     * @return
     */
    @PostMapping("/permission/batch-update-type")
    public ResultJson batchUpdateType(@RequestBody List<PermissionTypeVO> permissionTypeVOs, Developer developer){
        QueryWrapper<App> appQueryWrapper = new QueryWrapper<>();
        appQueryWrapper.select("id");
        appQueryWrapper.eq("develop_id", developer.getId());
        List<App> list = appService.list(appQueryWrapper);
        List<Integer> collect = list.stream().map(i -> i.getId()).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(list)){
            return ResultJson.fail("开发者暂无应用");
        }

        for (PermissionTypeVO permissionTypeVO : permissionTypeVOs) {
            if(CollectionUtils.isEmpty(permissionTypeVO.getIds())){
                log.info("没有传入可操作的id");
                continue;
            }
            PermissionTypeEnum permissionTypeEnum = PermissionTypeEnum.typeValueOf(permissionTypeVO.getType());
            if(null == permissionTypeEnum){
                log.warn("修改项目权限范围参数错误");
                continue;
            }

            // 操作仅限当前开发者下面的app
            QueryWrapper<Permission> permissionQueryWrapper = new QueryWrapper<>();
            permissionQueryWrapper.select("id");
            permissionQueryWrapper.in("id", permissionTypeVO.getIds());
            permissionQueryWrapper.in("app_id", collect);
            List<Permission> list1 = permissionService.list(permissionQueryWrapper);
            if(list1.isEmpty()){
                log.warn("修改项目权限范围查询到的权限集合参数错误");
                continue;
            }
            List<Integer> operatorIds = list1.stream().map(i -> i.getId()).collect(Collectors.toList());

            // 更新这些权限的类型
            UpdateWrapper<Permission> permissionUpdateWrapper = new UpdateWrapper<>();
            permissionUpdateWrapper.in("id", operatorIds);
            permissionUpdateWrapper.set("type", permissionTypeVO.getType());
            permissionService.update(permissionUpdateWrapper);

            if(PermissionTypeEnum.ENTERPRISE.type == permissionTypeVO.getType()){
                // 移除项目中关联的企业级菜单
                QueryWrapper<ProjectPermission> projectPermissionQueryWrapper = new QueryWrapper<>();
                projectPermissionQueryWrapper.in("permission_id", operatorIds);

                List<ProjectPermission> list2 = projectPermissionService.list(projectPermissionQueryWrapper);
                if(!list2.isEmpty()){
                    permissionGroupService.permissionGroupFilter(null);
                    projectPermissionService.remove(projectPermissionQueryWrapper);
                }
            }
        }
        return ResultJson.success();
    }

    /**
     * 查询
     *
     * @param page
     * @param permissionQuery
     * @param appId
     * @param clientType
     * @param industryId
     * @return
     */
    @RequestMapping(value = "/permission/page-list", method = RequestMethod.GET)
    public ResultJson query(Page page,
                            PermissionQuery permissionQuery,
                            @RequestHeader(value = "appId", required = true) String appId,
                            @RequestHeader(value = "clientType", required = true) Integer clientType,
                            @RequestHeader(value = "industryId", required = true) Short industryId) {
        Page<Permission> permissionPageList = permissionService.getPermissionPageList(page, permissionQuery);
        List<Permission> records = permissionPageList.getRecords();
        List<Integer> appIdList = records.stream().map(Permission::getAppId).collect(Collectors.toList());
        AppQuery appQuery = new AppQuery();
        appQuery.withIds(appIdList);
        List<App> apps = appService.list(appQuery);
        Map<Integer, App> appMap = apps.stream().collect(Collectors.toMap(App::getId, Function.identity()));
        List<PermissionDTO> resultList = new ArrayList<>();
        for (Permission permission : records) {
            Integer appIdKey = permission.getAppId();
            PermissionDTO permissionResult = new PermissionDTO();
            BeanUtils.copyProperties(permission, permissionResult);
            permissionResult.setAppIdStr(appMap.get(appIdKey).getAppId());
            //设置场景
            QueryWrapper<Scene> sceneQueryWrapper = new QueryWrapper<>();
            sceneQueryWrapper.eq("code",permission.getSceneCode());
            Scene scene = sceneDao.selectOne(sceneQueryWrapper);
            if(scene != null) {
                permissionResult.setSceneNames(scene.getName());
            }
            resultList.add(permissionResult);
        }
        Page<PermissionDTO> resultPageList = new Page<>();
        resultPageList.setTotal(permissionPageList.getTotal());
        resultPageList.setCurrent(permissionPageList.getCurrent());
        resultPageList.setSize(permissionPageList.getSize());
        resultPageList.setRecords(resultList);
        return ResultJson.success(resultPageList);
    }

    /**
     * 权限列表导出
     * @param permissionQuery
     * @return
     */
    @RequestMapping(value = "/permission/export", method = RequestMethod.POST)
    public void exportPermission(HttpServletResponse response, PermissionQuery permissionQuery) throws IOException {
        if (null == permissionQuery.getAppId()) {
            log.error("参数错误，缺少appId");
            return;
        }
        permissionQuery.setOrderColumn("created_at");
        permissionQuery.setOrderAsc(true);
        if (StringUtils.isNotEmpty(permissionQuery.getAppId())){
            App app = appService.getByAppId(permissionQuery.getAppId());
            permissionQuery.setAppIdPrimaryKey(app.getId());
        }
        List<Permission> permissionList = permissionService.getPermissionList(permissionQuery);
        String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy_MM_dd"));
        String fileName = "菜单权限" + time + ".xlsx";
        // 空文件流
        if (CollectionUtils.isEmpty(permissionList)) {
            ArrayList<PermissionExcelVO> emptyList = new ArrayList<>(permissionList.size());
            excelExportUtils.exportExcelStream(emptyList, PermissionExcelVO.class, null, "菜单权限",  fileName, response);
        }
        ArrayList<PermissionExcelVO> resultList = new ArrayList<>(permissionList.size());
        for (Permission permission : permissionList) {
            PermissionExcelVO permissionExcelVO = new PermissionExcelVO();
            permission.setAppIdStr(permissionQuery.getAppId());
            BeanUtils.copyProperties(permission, permissionExcelVO);
            //设置场景
            QueryWrapper<Scene> sceneQueryWrapper = new QueryWrapper<>();
            sceneQueryWrapper.eq("code",permission.getSceneCode());
            Scene scene = sceneDao.selectOne(sceneQueryWrapper);
            if(scene != null) {
                permissionExcelVO.setSceneNames(scene.getName());
            }
            resultList.add(permissionExcelVO);
        }
        excelExportUtils.exportExcelStream(resultList, PermissionExcelVO.class, null, "菜单权限",  fileName, response);
    }

    /**
     * 前台获取项目的权限树
     * @param permissionQuery
     * @return
     */
    @PostMapping("/permission/project-tree")
    public ResultJson getProjectPermission(@RequestHeader("industryId") Short industryId,
                                           @RequestBody PermissionQuery permissionQuery){
        if(null == permissionQuery.getProjectId()){
            return ResultJson.fail("项目参数错误");
        }
        PermissionTreeDTO permissionTreeDTO = new PermissionTreeDTO();
        permissionTreeDTO.setProjectId(permissionQuery.getProjectId());
        permissionTreeDTO.setPermissionType(PermissionTypeEnum.PROJECT);
        List<AppPermissionMenuDTO> permissionTree = permissionService.getPermissionTreeAdmin(permissionTreeDTO);
        List<AppPermissionMenuDTO> permissionTreeResult = new ArrayList<>();
        if (!CollectionUtils.isEmpty(permissionTree)) {
            for (AppPermissionMenuDTO appPermissionMenuDTO : permissionTree) {
                Short industryIdForPermission = appPermissionMenuDTO.getApp().getIndustryId();
                if (industryId.equals(industryIdForPermission)) {
                    permissionTreeResult.add(appPermissionMenuDTO);
                }
            }
            return ResultJson.success(permissionTreeResult);
        }
        return ResultJson.success(permissionTree);
    }

    @RequestMapping(value = "/permission/admin-import")
    public ResultJson adminImport(@RequestParam MultipartFile file) {
        List<Permission> permissions = ExcelUtils.readExcel(Permission.class, file, 2);
        return permissionService.adminBatchCreate(permissions);
    }

    /**
     * 权限组数据升级
     * @return
     */
    @GetMapping(value = "/permission/update-group")
    public ResultJson permissionUpdateGroup(){
        QueryWrapper<AccountRole> accountRoleQueryWrapper = new QueryWrapper<>();
        List<AccountRole> accountRoles = accountRoleService.list(accountRoleQueryWrapper);
        List<Integer> roleIds = accountRoles.stream().map(i -> i.getRoleId()).distinct().collect(Collectors.toList());
        List<Integer> accountIds = accountRoles.stream().map(i -> i.getAccountId()).distinct().collect(Collectors.toList());
        Map<Integer, List<Integer>> accountRoleMap = accountRoles.stream().collect(Collectors.groupingBy(AccountRole::getAccountId, Collectors.mapping(AccountRole::getRoleId, Collectors.toList())));
        List<Role> roles = roleService.listByIds(roleIds);
        Map<Integer, Role> roleMap = roles.stream().collect(Collectors.toMap(Role::getId, Function.identity()));
        List<PermissionGroup> permissionGroups = new ArrayList<>();

        QueryWrapper<PermissionGroup> permissionGroupQueryWrapper = new QueryWrapper<>();
        permissionGroupQueryWrapper.select("account_id");
        permissionGroupQueryWrapper.in("account_id", accountIds);
        List<PermissionGroup> list = permissionGroupService.list(permissionGroupQueryWrapper);
        List<Integer> existAccount = new ArrayList<>();
        if(!CollectionUtils.isEmpty(list)){
            existAccount = list.stream().map(i -> i.getAccountId()).distinct().collect(Collectors.toList());
        }
        for (Map.Entry<Integer, List<Integer>> entry : accountRoleMap.entrySet()) {
            // 已经存在的权限组表里的帐号不做升级
            if(existAccount.contains(entry.getKey())){
                log.info("帐号 {} 权限组数据已存在", entry.getKey());
                continue;
            }
            // 一个项目和项目角色+企业角色一组
            List<Role> collect = entry.getValue().stream().filter(j -> roleMap.get(j) !=null).map(i -> roleMap.get(i)).collect(Collectors.toList());
            log.info("当前帐号 {}, 角色数量 {}", entry.getKey(), collect.size());
            if(CollectionUtils.isEmpty(collect)){
                continue;
            }
            // 企业角色
            List<Role> collect1 = collect.stream().filter(i -> i.getProjectId() == null).distinct().collect(Collectors.toList());
            List<Integer> collect3 = collect1.stream().map(i -> i.getId()).collect(Collectors.toList());
            if(40 < collect3.size()){
                log.warn("角色数据过长不保存");
                continue;
            }
            // 项目角色
            Map<Integer, List<Integer>> collect2 = collect.stream().filter(i -> i.getProjectId() != null).distinct().collect(Collectors.groupingBy(Role::getProjectId, Collectors.mapping(Role::getId, Collectors.toList())));
            if(!CollectionUtils.isEmpty(collect2)){
                for (Map.Entry<Integer, List<Integer>> en : collect2.entrySet()) {
                    PermissionGroup permissionGroup = new PermissionGroup();
                    permissionGroup.setAccountId(entry.getKey());
                    String projectIds = en.getKey().toString();
                    if(220 < projectIds.length()){
                        log.warn("项目数据过长不保存");
                        continue;
                    }
                    permissionGroup.setProjectIds(projectIds);
                    List<Integer> value = en.getValue();
                    value.addAll(collect3);
                    permissionGroup.setRoleIds(Joiner.on(",").join(value));
                    permissionGroups.add(permissionGroup);
                }
            }else{
                // 直接给企业角色放一个组
                if(!CollectionUtils.isEmpty(collect1)){
                    PermissionGroup permissionGroup = new PermissionGroup();
                    permissionGroup.setAccountId(entry.getKey());
                    permissionGroup.setRoleIds(Joiner.on(",").join(collect3));
                    permissionGroups.add(permissionGroup);
                }
            }
        }
        permissionGroupService.saveBatch(permissionGroups);
        return ResultJson.success();
    }


    /**
     * 创建授权信息
     * @return
     */
    @PostMapping("/permission/auth/create")
    public ResultJson authCreate(@RequestBody PermissionAuthDTO permissionAuthDTO){
        return permissionAuthService.create(permissionAuthDTO);
    }

    /**
     * 授权信息详情
     * @return
     */
    @PostMapping("/permission/auth/detail")
    public ResultJson authDetail(@RequestBody PermissionAuth permissionAuth){
        if(null == permissionAuth.getPermissionId()){
            return ResultJson.fail("参数错误");
        }
        QueryWrapper<Permission> permissionQueryWrapper = new QueryWrapper<>();
        permissionQueryWrapper.eq("id", permissionAuth.getPermissionId());
        List<Permission> permissions = permissionService.list(permissionQueryWrapper);
        if(CollectionUtil.isEmpty(permissions)){
            return ResultJson.fail("菜单不存在");
        }
        QueryWrapper<PermissionAuth> permissionAuthQueryWrapper = new QueryWrapper<>();
        //permissionAuthQueryWrapper.eq("permission_id", permissionAuth.getPermissionId());
        //切换code关联
        permissionAuthQueryWrapper.eq("code", permissions.get(0).getCode());
        List<PermissionAuth> list = permissionAuthService.list(permissionAuthQueryWrapper);
        return ResultJson.success(list);
    }

    /**
     * 刷新系统的权限缓存
     * @return
     */
    @PostMapping("/permission/auth/refresh")
    public ResultJson authRefresh(){

        List<App> apps = appService.list();
        for (App app : apps) {
            log.info("正在刷新 {} 的授权信息", app.getName());
            // 获取当前app的菜单下面的所有授权信息
            QueryWrapper<Permission> permissionQueryWrapper = new QueryWrapper<>();
            permissionQueryWrapper.eq("app_id", app.getId());
            permissionQueryWrapper.select("code");
            List<Permission> permissions = permissionService.list(permissionQueryWrapper);
            if(CollectionUtils.isEmpty(permissions)){
                continue;
            }
            List<String> permissionCodes = permissions.stream().map(i -> i.getCode()).collect(Collectors.toList());
            QueryWrapper<PermissionAuth> permissionAuthQueryWrapper = new QueryWrapper<>();
            permissionAuthQueryWrapper.in("code", permissionCodes);
            List<PermissionAuth> list = permissionAuthService.list(permissionAuthQueryWrapper);
            if(CollectionUtils.isEmpty(list)){
                continue;
            }
            permissionAuthService.updateEveryServer(list, app.getId());
        }
        return ResultJson.success();
    }

    /**
     * 删除菜单的授权信息
     * @return
     */
    @PostMapping("/permission/auth/delete")
    public ResultJson authDelete(@RequestBody PermissionAuth permissionAuth){
        return permissionAuthService.delete(permissionAuth.getId());
    }


    @RequestMapping(value = "/permission/template-export")
    public void downloadTemplate(HttpServletResponse response) {
        String filePath = null;
        try {
            filePath = ResourceUtils.getURL("classpath:").getPath() + "template/permission/IMPORT_TEMPLATE.xlsx";
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        File file = new File(filePath);

        if (file.exists()) {
            response.setHeader("content-type", "application/octet-stream");
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=IMPORT_TEMPLATE.xlsx");
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            FileInputStream fis = null;
            BufferedInputStream bis = null;

            try {
                fis = new FileInputStream(file);

                Workbook workbook = null;
                try {
                    workbook = new XSSFWorkbook(fis);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                workbook.write(response.getOutputStream());
            } catch (Exception e) {
                log.error(e.getMessage());
            } finally {
                if (bis != null) {
                    try {
                        bis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        } else {
            log.error("文件 {} 不存在", filePath);
        }
    }

    /**
     * 权限组兼容旧数据 上线时请求一次 谨慎使用
     * @param maps 需要排除的app：industryId
     * @return
     */
    @PostMapping("/permission/cover-old-data")
    public ResultJson coverOldData(@RequestBody Map<String,Integer> maps){
        QueryWrapper<PermissionGroup> queryWrapper = new QueryWrapper<>();
        queryWrapper.isNull("enterprise_id")
                .isNotNull("role_ids");
        List<PermissionGroup> permissionGroups = permissionGroupService.list(queryWrapper);
        //查找企业角色
        QueryWrapper<Role> roleQueryWrapper = new QueryWrapper<>();
        roleQueryWrapper.select("id","enterprise_id");
        roleQueryWrapper.isNotNull("enterprise_id");
        List<Role> roles = roleService.list(roleQueryWrapper);
        //查找需要排除的角色
        List<Role> excludeRoles = new ArrayList<>();
        if (!CollectionUtils.isEmpty(maps)){
            for (Map.Entry<String,Integer> map : maps.entrySet()){
                roleQueryWrapper.clear();
                roleQueryWrapper.isNull("enterprise_id");
                roleQueryWrapper.eq("industry_id",map.getValue());
                roleQueryWrapper.eq("app_id",map.getKey());
                excludeRoles.addAll(roleService.list(roleQueryWrapper));
            }
        }
        //查找账号所在的企业
        Map<Integer,List<Enterprise>> entMap = accountService.findEnterpriseMap(permissionGroups.stream().distinct().map(PermissionGroup::getAccountId).collect(Collectors.toList()));
        //遍历所有权限组
        try {
            List<List<PermissionGroup>> parts = Lists.partition(permissionGroups, 500);
            for (List<PermissionGroup> permissionGroupList : parts){
                List<PermissionGroup> newData = new ArrayList<>();
                List<PermissionGroup> deleteData = new ArrayList<>();
                for (PermissionGroup permissionGroup : permissionGroupList){
                    if (null == permissionGroup.getRoleIds() || StringUtils.isEmpty(permissionGroup.getRoleIds())){
                        continue;
                    }
                    List<Integer> roleIds = Arrays.stream(permissionGroup.getRoleIds().split(",")).map(Integer::valueOf).collect(Collectors.toList());
                    //过滤出该权限组是否有企业角色
                    List<Role> roleList = roles.stream().filter(i -> roleIds.contains(i.getId())).collect(Collectors.toList());
                    //有企业角色则填充企业
                    if (!roleList.isEmpty()){
                        Integer entId = null;
                        for (Role role : roleList){
                            //遍历出企业角色、填充企业给权限组
                            if (null != role.getEnterpriseId()){
                                entId = role.getEnterpriseId();
                                break;
                            }
                        }
                        if (null != entId){
                            permissionGroup.setEnterpriseId(entId);
                            newData.add(permissionGroup);
                        }
                    }else {
                        //没有企业角色 需要判断是否含有需要过滤的角色
                        roleList = excludeRoles.stream().filter(i ->roleIds.contains(i.getId())).collect(Collectors.toList());
                        //如果不包含要过滤的角色&&账号有企业 则按照平台角色处理方法
                        if (roleList.isEmpty() && entMap.containsKey(permissionGroup.getAccountId())){
                            List<Enterprise> enterprises = entMap.get(permissionGroup.getAccountId());
                            if (!enterprises.isEmpty()){
                                //平台角色权限组根据企业数量新增
                                for (Enterprise enterprise :enterprises){
                                    PermissionGroup permissionGroup1 = new PermissionGroup();
                                    permissionGroup1.setRoleIds(permissionGroup.getRoleIds());
                                    permissionGroup1.setAccountId(permissionGroup.getAccountId());
                                    permissionGroup1.setProjectIds(permissionGroup.getProjectIds());
                                    permissionGroup1.setEnterpriseId(enterprise.getId());
                                    newData.add(permissionGroup1);
                                }
                                //并删掉原来的权限组
                                deleteData.add(permissionGroup);
                            }
                        }
                    }
                }
                permissionGroupService.saveOrUpdateBatch(newData);
                permissionGroupService.removeByIds(deleteData.stream().map(PermissionGroup::getId).collect(Collectors.toList()));
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return ResultJson.success();
    }

}


